home *** CD-ROM | disk | FTP | other *** search
- Subject: v16i053: Watchdog for users and machines
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: budd@bu-it.bu.edu (Phil Budne)
- Posting-number: Volume 16, Issue 53
- Archive-name: fido
-
- Fido periodically scans the files created by rwhod and reports the
- comings and goings of people and machines. It reads a .fido init file to
- determine what to watch. I run it as "fido &" in my console window.
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: README Makefile fido.c fido.1
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f README -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"README\"
- else
- echo shar: Extracting \"README\" \(331 characters\)
- sed "s/^X//" >README <<'END_OF_README'
- XFido is a program I wrote in anticipation of getting a workstation.
- XI keep it running in my console window. Recently it has become popular
- Xwith more users, and so I've done some cleanup and sent it out.
- X
- XI don't doubt that it is a great waste of CPU, but Hey, I like it.
- X
- X Phil Budne
- X Boston University, Boston Ma
- X August 1988
- END_OF_README
- if test 331 -ne `wc -c <README`; then
- echo shar: \"README\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f Makefile -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"Makefile\"
- else
- echo shar: Extracting \"Makefile\" \(341 characters\)
- sed "s/^X//" >Makefile <<'END_OF_Makefile'
- X# Makefile for fido.
- X# typing "make DEBUG=n" builds a fido of debug level n
- X#
- X# GNU's fantastic CC
- XCC=gcc
- XDFLAGS=-g
- XCFLAGS=-O
- XDEBUG=4
- X
- Xdfido$(DEBUG): fido.c
- X $(CC) $(DFLAGS) -DDEBUG=$(DEBUG) -o dfido$(DEBUG) fido.c
- X
- Xfido: fido.c
- X $(CC) $(CFLAGS) -o fido fido.c
- X
- XSHAR: README Makefile fido.c fido.1
- X shar README Makefile fido.c fido.1 > SHAR
- END_OF_Makefile
- if test 341 -ne `wc -c <Makefile`; then
- echo shar: \"Makefile\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f fido.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"fido.c\"
- else
- echo shar: Extracting \"fido.c\" \(19284 characters\)
- sed "s/^X//" >fido.c <<'END_OF_fido.c'
- X/*
- X * Copyright 1988 Philip L. Budne.
- X * All rights reserved.
- X *
- X * This program may be freely distributed as long as this notice
- X * and the above Copyright remain intact.
- X *
- X * The author makes no claims of suitability for use.
- X */
- X
- X/*
- X * Phil Budne @ BU/DSG
- X *
- X * prehistoric users list compiled into struct. machine
- X * watching was a seperate program.
- X * 8/1/86 read .fido file
- X * 1/87 check ppid
- X * 8/14/87 read rwho files directly (used to popen rwho!)
- X * 8/20/87 add beep again, add idletime
- X * rework -- put found structure in target
- X * report found users once -- now way to
- X * track where someone is gone from. report idle.
- X * 8/21/87 add machines, hungry
- X * 4/19/88 look in HOME for .fido, quit if not found
- X * stat WHODIR, keep list of files to avoid
- X * re-reading spooldir constantly!
- X * 8/6/88 convert to open mhash. malloc targets.
- X * add stomp. remove BEEP, STOMP, MT, HOST, AT
- X * use static filenamestrings.
- X * 8/8/88! keep boottime and sendtime in struct machine.
- X * report reboots.
- X * 8/9/88 All dressed up. Ready to go!
- X */
- X
- X/* do reverse video for machines? */
- X
- X# include <sys/types.h>
- X# include <sys/stat.h>
- X# include <sys/dir.h>
- X# include <strings.h>
- X# include <stdio.h>
- X# include <ctype.h>
- X# include <protocols/rwhod.h> /* But not on 4.2 systems!! */
- X
- X# define EOS '\0'
- Xextern char *malloc(); /* from libc */
- X
- X# define bool int
- X# define TRUE 1
- X# define FALSE 0
- X
- X# define INITFILE ".fido"
- X
- X# define DEF_BEEP FALSE
- X# define DEF_STAMP TRUE
- X# define DEF_MACHINES TRUE
- X# define DEF_DOWNTIME 8 /* minutes (less than 4 is noisy) */
- X# define DEF_IDLETIME 15 /* minutes */
- X# define DEF_SLEEPTIME 60 /* seconds */
- X# define MIN_SLEEPTIME 32
- X
- X# define MAXBUF 132 /* various buffers */
- X
- X/* static lengths in target struct (fields from utmp) */
- X# define MAXHST 33
- X# define MAXUSR 9
- X# define MAXTTY 9
- X
- X# define NUMFILES 100 /* grrr -- a hardwired limit!! */
- X# define BPHOST 32 /* avg length for hostnames ick!! */
- X
- Xstruct target {
- X char *host, *user;
- X struct found { /* count of entries found in each state */
- X int nidle, idle, hungry;
- X } found[2]; /* now and before */
- X struct target *tnext;
- X};
- X# define TOTAL(tp,t) ((tp)->found[t].idle + (tp)->found[t].nidle)
- X
- Xstruct target *targets; /* list of targets */
- Xstruct target *lasttarget; /* last target created */
- Xint numt = 0; /* number of targets */
- Xint this = 0; /* toggling index (0/1) into found array */
- X
- Xchar wildhost[] = "*";
- X# define WILDHOST wildhost /* empty host for targets */
- X
- Xint beep = DEF_BEEP;
- Xint stamp = DEF_STAMP;
- Xint machines = DEF_MACHINES;
- Xint downtime = DEF_DOWNTIME * 60;
- Xint idletime = DEF_IDLETIME * 60;
- Xint sleeptime = DEF_SLEEPTIME;
- X
- Xchar nowstr[ 50 ]; /* for time stomping */
- X
- Xstruct machine { /* hash table of machines */
- X char name[40];
- X enum { UP=1, DOWN=2 } state;
- X time_t latest; /* last time seen up */
- X int boottime, sendtime; /* from whod packet */
- X struct machine
- X *hnext, /* next in hash chain */
- X *anext; /* next in list of all hosts */
- X};
- X
- X# define MHSIZE 101 /* small prime */
- Xstruct machine *mhash[ MHSIZE ], *allmachines;
- Xint firstpass = TRUE;
- X
- X# if DEBUG > 0
- Xchar *state_name[] = { "??", "UP", "DOWN" };
- X# endif /* DEBUG > 0 */
- X
- X# define WHODIR "/usr/spool/rwho"
- X
- X# define ISHUNGRY(we) \
- X ((we->we_utmp.out_line[sizeof(we->we_utmp.out_line)-1] & 0200) != 0 )
- X
- X# define CLEARHUNGRY(we) \
- X we->we_utmp.out_line[sizeof(we->we_utmp.out_line)-1] &= ~0200
- X
- Xmain() {
- X int i;
- X
- X if( !readinit( INITFILE ) ) { /* check current dir */
- X extern char *getenv();
- X char tname[ 1024 ], *hp;
- X
- X if( (hp = getenv("HOME")) == NULL ) { /* check 'home' */
- X /* getpwuid(getuid()) */
- X fprintf( stderr, "No ./.fido and HOME not set\n" );
- X exit( 1 );
- X } /* no HOME */
- X sprintf( tname, "%s/%s", hp, INITFILE );
- X if( !readinit( tname ) ) {
- X fprintf( stderr, "No ./.fido or %s\n", tname );
- X exit( 1 );
- X } /* readinit failed */
- X } /* no .fido in "." */
- X
- X# if DEBUG > 0
- X dumpinit();
- X# endif /* DEBUG > 0 */
- X
- X if( numt == 0 && !machines ) {
- X fprintf(stderr, "Nothing to do!!\n" );
- X exit( 1 );
- X } /* nothing to do!! */
- X
- X if( chdir( WHODIR ) < 0 ) {
- X perror( WHODIR );
- X exit( 1 );
- X } /* chdir failed */
- X
- X nice( 10 ); /* be nice to real users */
- X
- X for( ; ; ) {
- X dowho(); /* prowl rwho spool dir */
- X if( machines ) /* watching machines? */
- X scan(); /* yell about them */
- X this = !this; /* toggle found index */
- X fflush( stdout );
- X sleep( sleeptime ); /* go to sleep */
- X if( getppid() == 1 ) /* child of init? */
- X exit( 1 ); /* quitting time */
- X } /* for ever */
- X} /* main */
- X
- Xdowho() { /* poke thru rwho spool */
- X register int i;
- X register struct target *tp;
- X
- X int now;
- X char **fp;
- X struct whod wd;
- X struct stat newstat;
- X char buf[MAXBUF], user[MAXUSR], host[MAXHST], tty[MAXTTY];
- X
- X static int nfiles;
- X static struct stat oldstat;
- X static char *filenames[ NUMFILES ]; /* ACK!! hardwired limits! */
- X static char filenamestrings[ NUMFILES * BPHOST ]; /* avoid malloc/free */
- X
- X if( stat( ".", &newstat ) < 0 )
- X return;
- X
- X if( newstat.st_mtime != oldstat.st_mtime ) {
- X DIR *dirp;
- X struct direct *d;
- X register char *dp;
- X
- X oldstat = newstat;
- X# if DEBUG > 0
- X puts("(re)reading RWHODIR");
- X# endif /* DEBUG > 0 */
- X
- X if( (dirp = opendir( "." )) == NULL )
- X return;
- X
- X nfiles = 0;
- X fp = filenames;
- X dp = filenamestrings;
- X while( (d = readdir( dirp )) != NULL ) {
- X register char *sp;
- X
- X if( strncmp( d->d_name, "whod.", 5 ) != 0 )
- X continue;
- X
- X# if DEBUG > 4
- X printf("readdir: %s\n", d->d_name );
- X# endif /* DEBUG > 4 */
- X if( nfiles == NUMFILES ) {
- X fprintf( stderr, "Too many files!! Increase NUMFILES!!\n");
- X break;
- X } /* too many files */
- X
- X nfiles++;
- X *fp++ = dp;
- X sp = d->d_name;
- X while( *dp++ = *sp++ )
- X ;
- X } /* while readdir */
- X closedir( dirp );
- X } /* rwhod mtime has changed */
- X
- X for( tp = targets, i = 0; i < numt; tp = tp->tnext, i++ ) {
- X tp->found[this].hungry = 0;
- X tp->found[this].nidle = 0;
- X tp->found[this].idle = 0;
- X } /* for i */
- X
- X time( &now );
- X if( stamp ) {
- X strcpy( nowstr, ctime( &now ) );
- X nowstr[ 16 ] = ' ';
- X nowstr[ 17 ] = EOS; /* kill year and seconds */
- X } /* stamping */
- X
- X for( fp = filenames, i = 0; i < nfiles; i++, fp++ ) {
- X register struct whoent *we;
- X int f, cc, down;
- X time_t recvtime;
- X int try;
- X# ifdef USEFILETIME
- X struct stat ftime;
- X# endif /* USEFILETIME defined */
- X
- X# if DEBUG > 19
- X printf("=== %s ===\n", *fp );
- X# endif /* DEBUG > 19 */
- X
- X for( try = 0; try < 5; try++, sleep(1) ) {
- X cc = -1;
- X if( (f = open( *fp, 0 )) < 0 )
- X continue; /* try to read again */
- X
- X cc = read( f, &wd, sizeof( wd ));
- X# ifdef USEFILETIME
- X fstat( f, &ftime );
- X# endif /* USEFILETIME defined */
- X close( f );
- X
- X cc -= sizeof( wd ) - sizeof ( wd.wd_we );
- X# if DEBUG > 19
- X printf("%d chars\n", cc );
- X# endif /* DEBUG > 19 */
- X if( cc < 0 ) {
- X# if DEBUG > 0 && DEBUG < 20
- X printf("%s: %d chars\n", wd.wd_hostname, cc );
- X# endif /* DEBUG > 0 && DEBUG < 20 */
- X continue; /* re-read file */
- X } /* short file */
- X else
- X break;
- X } /* for each try */
- X if( cc < 0 )
- X continue; /* re-read */
- X
- X# ifdef USEFILETIME
- X recvtime = ftime.st_mtime;
- X# else /* USEFILETIME not defined */
- X recvtime = wd.wd_recvtime;
- X# endif /* USEFILETIME not defined */
- X
- X down = now - recvtime;
- X# if DEBUG > 19
- X printf( "down %d\n", down );
- X# endif /* DEBUG > 19 */
- X
- X if( wd.wd_hostname[0] == EOS ) {
- X# if DEBUG > 0
- X printf( "null hostname in file %s\n", *fp );
- X# endif /* DEBUG > 0 */
- X continue; /* re-read!? */
- X } /* hostname empty */
- X
- X if( machines )
- X if( wd.wd_hostname[0] != EOS )
- X process( &wd, recvtime );
- X
- X if( down > downtime ) /* host is down? */
- X continue;
- X
- X for( we = wd.wd_we; cc > 0 ; we++, cc -= sizeof( *we ) ) {
- X int tcnt;
- X int washungry;
- X register char *cp, *dp;
- X
- X washungry = ISHUNGRY(we); /* save hungry bit */
- X CLEARHUNGRY(we); /* clear to avoid bad comparisons */
- X
- X strncpy( user, we->we_utmp.out_name, 8 );
- X strcpy( host, wd.wd_hostname );
- X strcpy( tty, we->we_utmp.out_line );
- X
- X# if DEBUG > 10
- X printf("%s@%s %s idle %d\n", user, host, tty, we->we_idle );
- X# endif /* DEBUG > 10 */
- X
- X for( tp = targets, tcnt = 0; tcnt < numt; tcnt++, tp = tp->tnext ) {
- X if( strcmp(user, tp->user) == 0 ) { /* matching user */
- X if( (dp = index( host, '.' )) != NULL )
- X *dp = EOS; /* strip domains */
- X
- X# if DEBUG > 4
- X# if DEBUG < 20
- X printf("%s@%s %s idle %d\n",
- X user, host, tty, we->we_idle );
- X# endif /* DEBUG < 20 */
- X printf("%s %d %d\n", tp->user,
- X tp->found[this].nidle,
- X tp->found[this].idle );
- X# endif /* DEBUG > 4 */
- X
- X if( tp->host == WILDHOST || /* wild or */
- X strcmp(host, tp->host) == 0 ) { /*matching host*/
- X if( we->we_idle > idletime )
- X tp->found[this].idle++;
- X else { /* not idle */
- X if( tp->found[this].nidle++ == 0 && /*first*/
- X tp->found[!this].nidle == 0 ) { /*none b4*/
- X# if DEBUG > 0 && DEBUG < 5
- X tprint( tp );
- X# endif /* DEBUG > 0 && DEBUG < 5 */
- X /* nothing before or, imbalance */
- X if( tp->found[!this].idle == 0 ||
- X TOTAL(tp,this) > TOTAL(tp,!this) )
- X now_on( user, host, tty );
- X else /* return from idleness */
- X now_active( user, host, tty );
- X } /* first non idle where none before */
- X } /* not idle */
- X if( washungry )
- X if( tp->found[this].hungry++ == 0 &&
- X tp->found[!this].hungry == 0 )
- X now_hungry( user, host, tty );
- X } /* matching host */
- X goto nextwhoent;
- X } /* matching user */
- X } /* for all targets */
- X nextwhoent: ;
- X } /* for we */
- X } /* for each file */
- X
- X for( tp = targets, i = 0; i < numt; i++, tp = tp->tnext ) {
- X# if DEBUG > 49
- X tprint( tp );
- X# endif /* DEBUG > 49 */
- X if( tp->found[!this].nidle > 0 ) { /* was here before */
- X# if DEBUG > 4 && DEBUG < 50
- X tprint( tp );
- X# endif /* DEBUG > 4 && DEBUG < 50 */
- X if( tp->found[this].nidle == 0 ) { /* no non idle users */
- X# if DEBUG > 0 && DEBUG < 5
- X tprint( tp );
- X# endif /* DEBUG > 0 && DEBUG < 5 */
- X if( tp->found[this].idle > 0 && /* have idle users */
- X TOTAL(tp,this) == TOTAL(tp,!this) ) /* no net change */
- X now_idle( tp->user, tp->host );
- X else
- X now_gone( tp->user, tp->host ); /* none idle or */
- X /* net change. */
- X /* must have logged out */
- X } /* no non-idle */
- X } /* prev had non-idle */
- X else if( tp->found[!this].idle > 0 ) { /* prev idle? */
- X if( TOTAL(tp,this) == 0 ) { /* no current */
- X# if DEBUG > 0 && DEBUG < 5
- X tprint( tp );
- X# endif /* DEBUG > 0 && DEBUG < 5 */
- X now_gone( tp->user, tp->host );
- X }
- X } /* here but idle before */
- X } /* for tp */
- X} /* do who */
- X
- Xnow_on( user, host, tty )
- X char *user, *host, *tty;
- X{
- X stomp();
- X printf("bow wow!! %s now on %s %s\n", user, host, tty );
- X} /* now on */
- X
- Xnow_active( user, host, tty )
- X char *user, *host, *tty;
- X{
- X stomp();
- X printf("arf! %s active on %s %s\n", user, host, tty );
- X} /* now active */
- X
- Xnow_hungry( user, host, tty )
- X char *user, *host, *tty;
- X{
- X stomp();
- X printf("woof! %s hungry on %s %s\n", user, host, tty );
- X} /* now hungry */
- X
- Xnow_idle( user, host )
- X char *user, *host;
- X{
- X stomp();
- X /* doggie noise here? */
- X fputs( user, stdout );
- X if( host != WILDHOST ) {
- X putchar('@');
- X fputs( host, stdout );
- X } /* have host */
- X puts(" is idle");
- X} /* now idle */
- X
- Xnow_gone( user, host )
- X char *user, *host;
- X{
- X stomp();
- X /* doggie noise here? */
- X fputs( user, stdout );
- X if( host != WILDHOST ) {
- X putchar('@');
- X fputs( host, stdout );
- X } /* have host */
- X puts(" is gone");
- X} /* now gone */
- X
- Xnow_sated( user, host )
- X char *user, *host;
- X{
- X stomp();
- X /* doggie noise here? */
- X fputs( user, stdout );
- X if( host != WILDHOST ) {
- X putchar('@');
- X fputs( host, stdout );
- X } /* have host */
- X puts(" is sated!!");
- X} /* now sated */
- X
- Xbool
- Xcheckflag( buf, name, ptr )
- X char *name, *buf;
- X bool *ptr;
- X{
- X int l;
- X
- X l = strlen( name );
- X if( strncmp( name, buf, l ) == 0 )
- X *ptr = TRUE;
- X else if( buf[0] == 'n' && buf[1] == 'o' && strncmp( name, buf+2, l ) == 0 )
- X *ptr = FALSE;
- X else
- X return( FALSE );
- X return( TRUE );
- X} /* checkflag */
- X
- Xbool
- Xnumarg( buf, name, ptr, scale )
- X char *name, *buf;
- X int *ptr, scale;
- X{
- X if( strncmp( name, buf, strlen( name ) ) == 0 ) {
- X int i;
- X if( sscanf( buf, "%*s %d", &i ) != 1 )
- X fprintf( stderr, "fido: bad line: %s\n", buf );
- X else
- X *ptr = i * scale;
- X return( TRUE );
- X } /* matches */
- X return( FALSE );
- X} /* numarg */
- X
- Xbool
- Xreadinit( file )
- X char *file;
- X{
- X FILE *f;
- X char buf[ MAXBUF ];
- X
- X if( (f = fopen(file, "r")) == NULL )
- X return( FALSE );
- X
- X while( fgets(buf, sizeof buf, f) != NULL ) {
- X register char *cp;
- X
- X if( (cp = index(buf,'\n')) != NULL )
- X *cp = EOS;
- X
- X# if DEBUG > 9
- X printf("%s\n", buf );
- X# endif /* DEBUG > 9 */
- X
- X if( buf[0] == '#' )
- X continue;
- X
- X if( strncmp(buf, "user", 4) == 0 )
- X r_user( buf );
- X else if( checkflag(buf, "beep", &beep) )
- X continue;
- X else if( checkflag(buf, "machines", &machines) )
- X continue;
- X else if( checkflag(buf, "stamp", &stamp) )
- X continue;
- X else if( numarg(buf, "idletime", &idletime, 60) )
- X continue;
- X else if( numarg(buf, "downtime", &downtime, 60) )
- X continue;
- X else if( numarg(buf, "sleeptime", &sleeptime, 1) )
- X continue;
- X else
- X fprintf(stderr, "fido: bad line in %s: %s\n", file, buf );
- X } /* while */
- X if( sleeptime < MIN_SLEEPTIME )
- X sleeptime = MIN_SLEEPTIME;
- X fclose ( f );
- X return( TRUE );
- X} /* readinit */
- X
- Xchar *savestr( s )
- Xregister char *s;
- X{
- X register char *t;
- X
- X while( *s != EOS && isspace( *s ) )
- X s++;
- X if( *s == EOS )
- X return( "" );
- X
- X t = s;
- X while( *t != EOS && !isspace( *t ) && *t != '\n' )
- X t++;
- X if( *t != EOS )
- X *t = EOS;
- X
- X# if DEBUG > 10
- X printf("savestr '%s'\n", s);
- X# endif /* DEBUG > 10 */
- X
- X return( strcpy( malloc( strlen( s ) + 1 ), s) );
- X
- X} /* savestr */
- X
- Xr_user( l )
- Xregister char *l;
- X{
- X register char *cp;
- X register struct target *tp;
- X
- X while( *l != EOS && !isspace( *l ) )
- X l++;
- X
- X while( *l != EOS && isspace( *l ) )
- X l++;
- X
- X if( *l == EOS )
- X return;
- X
- X tp = (struct target *) malloc( sizeof( struct target ) );
- X tp->tnext = NULL;
- X
- X if( targets == NULL )
- X targets = tp;
- X else
- X lasttarget->tnext = tp;
- X
- X if( (cp = index(l, '@')) != NULL ) {
- X *cp++ = EOS; /* blast @ to tie off user */
- X if( *cp != EOS ) /* have host? */
- X tp->host = savestr( cp ); /* save it */
- X else /* none? */
- X tp->host = WILDHOST; /* WTF -- save as wild */
- X } /* have host */
- X else
- X tp->host = WILDHOST;
- X tp->user = savestr( l );
- X
- X tp->found[0].idle = 0;
- X tp->found[0].nidle = 0;
- X tp->found[0].hungry = 0;
- X tp->found[1].idle = 0;
- X tp->found[1].nidle = 0;
- X tp->found[1].hungry = 0;
- X
- X lasttarget = tp;
- X numt++;
- X} /* r_user */
- X
- Xdumpinit() {
- X register int i;
- X register struct target *tp;
- X
- X for( tp = targets, i = 0; i < numt; tp = tp->tnext, i++ )
- X if( tp->host == WILDHOST )
- X printf("%s\n", tp->user );
- X else
- X printf("%s@%s\n", tp->user, tp->host );
- X} /* dumpinit */
- X
- X/**************** machine stuff ****************/
- X
- X# define SH 7
- X# define WS 32
- Xunsigned
- Xhash( n )
- X register char *n;
- X{
- X register unsigned l, i;
- X
- X i = l = 0;
- X while( *n != EOS ) {
- X i = ((i << SH) | (i >> (WS-SH))) ^ *n++;
- X l++;
- X } /* while not end of string */
- X return( (i + l) % MHSIZE );
- X} /* hash */
- X
- Xstruct machine *
- Xfindmachine( n )
- X char *n;
- X{
- X int h;
- X register struct machine *mp;
- X
- X h = hash( n );
- X for( mp = mhash[ h ]; mp != NULL; mp = mp->hnext )
- X if( strcmp(mp->name, n) == 0 )
- X return( mp );
- X return( NULL );
- X} /* findmachine */
- X
- Xstruct machine *
- Xnewmachine( n )
- X char *n;
- X{
- X int h;
- X register struct machine *mp;
- X
- X mp = (struct machine *) malloc( sizeof( struct machine ) );
- X strcpy(mp->name, n);
- X mp->state = UP;
- X
- X mp->anext = allmachines; /* put in list of all machines */
- X allmachines = mp;
- X
- X h = hash( n ); /* put in hash list */
- X mp->hnext = mhash[ h ];
- X mhash[ h ] = mp;
- X
- X if( !firstpass )
- X saynew( mp );
- X
- X return( mp );
- X} /* newmachine */
- X
- Xprocess( wd, t )
- X struct whod *wd;
- X time_t t;
- X{
- X struct machine *mp;
- X
- X if( (mp = findmachine( wd->wd_hostname )) != NULL ) {
- X# if DEBUG > 10
- X printf("found machine: %s\n", wd->wd_hostname);
- X# endif /* DEBUG > 10 */
- X if( wd->wd_boottime - mp->boottime > 120 ) { /* filter out freaks */
- X sayreboot( mp );
- X# if DEBUG > 0
- X printf("new %d old %d diff %d\n",
- X wd->wd_boottime,
- X mp->boottime,
- X wd->wd_boottime - mp->boottime );
- X# endif /* DEBUG > 0 */
- X } /* new boottime */
- X } /* machine found */
- X else
- X mp = newmachine( wd->wd_hostname );
- X
- X mp->latest = t; /* packet sendtime or file time */
- X mp->boottime = wd->wd_boottime;
- X mp->sendtime = wd->wd_sendtime;
- X} /* process */
- X
- Xscan() {
- X register struct machine *mp;
- X int i;
- X time_t now;
- X
- X time( &now );
- X for( mp = allmachines; mp != NULL; mp = mp->anext ) {
- X# if DEBUG > 4
- X printf("scan: %s (%s)\n", mp->name, state_name[ mp->state+1 ] );
- X# endif /* DEBUG > 4 */
- X /*
- X * if /usr/spool/rwho is on another machine (via NFS) and our
- X * clocks differ we get alot of up/down noise. there must be
- X * a good way to dampen this!!
- X *
- X * perhaps keep a new state "may be down" as a cushion
- X *
- X * perhaps keep threshold per host and increase each time the
- X * host comes "up" without having been rebooted (see
- X * wd_boottime)
- X */
- X if( now - mp->latest > downtime ) { /* now down */
- X if( mp->state != DOWN ) {
- X saydown( mp, now - mp->latest );
- X mp->state = DOWN;
- X } /* new state: down */
- X } /* now down */
- X else { /* now up */
- X if( mp->state != UP ) {
- X sayup( mp );
- X mp->state = UP;
- X } /* new state: up */
- X } /* now up */
- X } /* for all machines */
- X firstpass = FALSE;
- X} /* scan */
- X
- Xstomp() {
- X if( beep )
- X putchar('\007');
- X if( stamp )
- X fputs( nowstr, stdout );
- X} /* stomp */
- X
- Xsaydown( mp, t )
- X struct machine *mp;
- X int t;
- X{
- X int d, h, m;
- X
- X stomp();
- X printf("%s is down (", mp->name );
- X t /= 60; /* toss seconds */
- X m = t % 60; /* get mins */
- X t /= 60; /* toss mins */
- X d = t % 24; /* get days */
- X t /= 24; /* cast out days */
- X t %= 7; /* get weeks!! */
- X if( t > 0 ) printf("%dw", t );
- X if( d > 0 ) printf("%dd", d );
- X if( h > 0 ) printf("%dh", h );
- X if( m > 0 ) printf("%dm", m );
- X puts(")");
- X} /* saydown */
- X
- Xsayup( mp )
- X struct machine *mp;
- X{
- X stomp();
- X printf("%s is up\n", mp->name );
- X} /* sayup */
- X
- Xsaynew( mp )
- X struct machine *mp;
- X{
- X stomp();
- X printf("new machine: %s\n", mp->name );
- X} /* saynew sayme */
- X
- Xsayreboot( mp )
- X struct machine *mp;
- X{
- X stomp();
- X printf("%s rebooted\n", mp->name );
- X} /* saynew sayme */
- X
- X# if DEBUG > 0
- Xtprint( tp )
- X register struct target *tp;
- X{
- X printf("%s (%d %d %d) (%d %d %d)",
- X tp->user,
- X
- X tp->found[this].nidle,
- X tp->found[this].idle,
- X tp->found[this].hungry,
- X
- X tp->found[!this].nidle,
- X tp->found[!this].idle,
- X tp->found[!this].hungry
- X );
- X if( TOTAL(tp,this) != TOTAL(tp,!this) )
- X printf(" ***** net imbalance!! *****");
- X puts("");
- X} /* tprint */
- X# endif /* DEBUG > 0 */
- END_OF_fido.c
- if test 19284 -ne `wc -c <fido.c`; then
- echo shar: \"fido.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f fido.1 -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"fido.1\"
- else
- echo shar: Extracting \"fido.1\" \(2894 characters\)
- sed "s/^X//" >fido.1 <<'END_OF_fido.1'
- X.\"-*-nroff-*-
- X.TH FIDO 1 "9 Aug 1988"
- X.SH NAME
- Xfido \- a watchdog for users and machines
- X.SH SYNOPSIS
- X.B fido &
- X.SH FEATURES
- X.I Fido
- Xperiodically scans the files created by
- X.IR rwhod (8c)
- Xand reports the commings and goings of people and machines.
- X.I Fido
- Xreads a
- X.I .fido
- Xinit file to determine what to watch.
- X.I .fido
- Xis first checked for in the current directory, and then
- Xin the directory contained in the
- X.B \s-1HOME\s0
- Xenvironment variable.
- X.PP
- XThe
- X.I .fido
- Xfile consists of a list of commands from the list below.
- XLines starting with a hash-mark (#) are discarded as comments.
- X.HP
- X.B user
- X.IR user [@ host ]
- X.br
- XWatch for a specified user. Normally only the first login and last
- Xlogout of the specified user will be reported. If a host is
- Xspecified, then only instances of that user on that host are reported
- X(useful when multiple users have the same name). You can have
- Xmultiple lines with the same username and different hosts (including
- Xthe form with no host).
- X.HP
- X.RB [ no ] beep
- X.br
- XRing bell on output (default is
- X.BR nobeep )
- X.HP
- X.RB [ no ] machines
- X.br
- XWatch machines go up and down (default is
- X.BR machines )
- X.HP
- X.RB [ no ] stamp
- X.br
- XOutput timestamps. (default is
- X.BR stamp )
- X.HP
- X.B idletime
- X.I minutes
- X.br
- XSpecify the
- Xnumber of minutes until a user is declared idle (default is 15).
- X.HP
- X.B downtime
- X.I minutes
- X.br
- XSpecify the number of minutes before a host is declared down (default is 8).
- X.B Note!!
- XIf the
- X.IR rwho (1c)
- Xspool directory is located on another (NFS) host, a skew between
- Xtime of day clocks can cause major misery.
- X.HP
- X.B sleeptime
- X.I seconds
- X.br
- XSpecify number of seconds to sleep between scans (default is 60,
- Xminimum is 32).
- X.PP
- XYou must specify at least one
- X.B user
- Xline or
- X.B machines
- Xin your
- X.I .fido
- Xfile, otherwise
- X.I fido
- Xhas nothing to to!!
- XEach time it wakes up
- X.I fido
- Xchecks to see if it's parent pid is now pid 1 (init), if this
- Xis true, then
- X.IR fido 's
- Xorginal parent must have exited, and so
- X.I fido
- Xfollows its master into oblivion.
- X.SH FILES
- X.TP 20
- X.I /usr/spool/rwho
- Xrwho spool area
- X.PD 0
- X.TP
- X.I ./.fido
- Xfido init file first choice
- X.TP
- X.RI $\s-1HOME\s0 /.fido
- Xfido init file
- X.PD
- X.SH SEE ALSO
- X.IR who (1),
- X.IR rwho (1c),
- X.IR ruptime (1c),
- X.IR environ (5v),
- X.IR rwhod (8c),
- X.IR hungry (l)
- X.SH AUTHOR
- XPhilip L. Budne, Boston University, Distributed Systems Group
- X.SH BUGS
- XSee features.
- X.PP
- XNo way to exclude a given machine, or user on a given machine.
- X.PP
- XNo way to specify a particular terminal line.
- X.PP
- XNo way to specify any user on a given host (ie; watch for idle
- Xworkstations)
- X.PP
- X.I Fido
- Xwas inspired by a program of the same name running on the MIT
- XITS operating system for PDP-10s.
- X.PP
- X.I Fido
- Xcan only read 100 files from
- X.I /usr/spool/rwho
- X(see
- X.B \s-1NUMFILES\s0
- Xin the source)
- Xand the total number of bytes consumed by the filenames
- Xcannot exceed
- X.BR \s-1BPHOST\s0 "*" \s-1NUMFILES\s0 .
- X.RB ( \s-1BPHOST\s0
- Xis currently 32)
- END_OF_fido.1
- if test 2894 -ne `wc -c <fido.1`; then
- echo shar: \"fido.1\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of shell archive.
- exit 0
-
-